/*
*********************************************************************************************************
*
*
*                              Motorola S-records Support package
*                                        S-records 支持包
*
* File    : SRecord.h
* By      : Lin Shijun(http://blog.csdn.net/lin_strong)
* Date    : 2018/03/03
* Version : V1.0
* Note    : 1. This package provide the functions for converting between the S-record and the
*                corresponding string.
*              这个包提供了S-record与字符串间的转换函数
*           2. The package supposed the letter in the string in upper case. user should make
*                sure for that.
*              工具包默认字符串中的字母都是大写的，用户需要保证这件事。
*           3. the first thing to do with this package is to check the TYPE DEFINE.
*              用这个包的第一步是检测下定义的类型对不对
*
* the follow description of Motorola S-records Format is from
*    http://www.amelek.gda.pl/avr/uisp/srecord.htm
* chinese version: http://blog.csdn.net/lin_strong/article/details/78521950
*
* NAME
*   srec - S-record file and record format
* DESCRIPTION
*
*   An S-record file consists of a sequence of specially formatted ASCII character strings. An S-record
* will be less than or equal to 78 bytes in length.
*
*   The order of S-records within a file is of no significance and no particular order may be assumed.
*
*   The general format of an S-record follows:
*
*   +-------------------//------------------//-----------------------+
*   | type | count | address  |            data           | checksum |
*   +-------------------//------------------//-----------------------+
*
*   type -- A char[2] field. These characters describe the type of record (S0, S1, S2, S3, S5, S7, S8, or S9).
*
*   count -- A char[2] field. These characters when paired and interpreted as a hexadecimal value, display the
* count of remaining character pairs in the record.
*
*   address -- A char[4,6, or 8] field. These characters grouped and interpreted as a hexadecimal value, display
* the address at which the data field is to be loaded into memory. The length of the field depends on the number
* of bytes necessary to hold the address. A 2-byte address uses 4 characters, a 3-byte address uses 6 characters,
* and a 4-byte address uses 8 characters.
*
*   data -- A char [0-64] field. These characters when paired and interpreted as hexadecimal values represent
* the memory loadable data or descriptive information.
*
*   checksum -- A char[2] field. These characters when paired and interpreted as a hexadecimal value display the
* least significant byte of the ones complement of the sum of the byte values represented by the pairs of
* characters making up the count, the address, and the data fields.
*
*   Each record is terminated with a line feed. If any additional or different record terminator(s) or delay
* characters are needed during transmission to the target system it is the responsibility of the transmitting
* program to provide them.
*
*   S0 Record. The type of record is 'S0' (0x5330). The address field is unused and will be filled with zeros
* (0x0000). The header information within the data field is divided into the following subfields.
*
*     mname is char[20] and is the module name.
*     ver is char[2] and is the version number.
*     rev is char[2] and is the revision number.
*     description is char[0-36] and is a text comment.
*
*     Each of the subfields is composed of ASCII bytes whose associated characters, when paired, represent one
* byte hexadecimal values in the case of the version and revision numbers, or represent the hexadecimal values
* of the ASCII characters comprising the module name and description.
*
*   S1 Record. The type of record field is 'S1' (0x5331). The address field is intrepreted as a 2-byte address.
* The data field is composed of memory loadable data.
*
*   S2 Record. The type of record field is 'S2' (0x5332). The address field is intrepreted as a 3-byte address.
* The data field is composed of memory loadable data.
*
*   S3 Record. The type of record field is 'S3' (0x5333). The address field is intrepreted as a 4-byte address.
* The data field is composed of memory loadable data.
*
*   S5 Record. The type of record field is 'S5' (0x5335). The address field is intrepreted as a 2-byte value and
* contains the count of S1, S2, and S3 records previously transmitted. There is no data field.
*
*   S7 Record. The type of record field is 'S7' (0x5337). The address field contains the starting execution
* address and is intrepreted as 4-byte address. There is no data field.
*
*   S8 Record. The type of record field is 'S8' (0x5338). The address field contains the starting execution
* address and is intrepreted as 3-byte address. There is no data field.
*
*   S9 Record. The type of record field is 'S9' (0x5339). The address field contains the starting execution
* address and is intrepreted as 2-byte address. There is no data field.
*
* EXAMPLE
*
*   Shown below is a typical S-record format file.
*
*     S00600004844521B
*     S1130000285F245F2212226A000424290008237C2A
*     S11300100002000800082629001853812341001813
*     S113002041E900084E42234300182342000824A952
*     S107003000144ED492
*     S5030004F8
*     S9030000FC
*
*   The file consists of one S0 record, four S1 records, one S5 record and an S9 record.

*   The S0 record is comprised as follows:

*     S0 S-record type S0, indicating it is a header record.
*     06 Hexadecimal 06 (decimal 6), indicating that six character pairs (or ASCII bytes) follow.
*     00 00 Four character 2-byte address field, zeroes in this example.
*     48 44 52 ASCII H, D, and R - "HDR".
*     1B The checksum.
*
*   The first S1 record is comprised as follows:
*
*     S1 S-record type S1, indicating it is a data record to be loaded at a 2-byte address.
*     13 Hexadecimal 13 (decimal 19), indicating that nineteen character pairs, representing a 2 byte address,
*  16 bytes of binary data, and a 1 byte checksum, follow.
*     00 00 Four character 2-byte address field; hexidecimal address 0x0000, where the data which follows is
*  to be loaded.
*     28 5F 24 5F 22 12 22 6A 00 04 24 29 00 08 23 7C Sixteen character pairs representing the actual binary
*  data.
*     2A The checksum.
*
*   The second and third S1 records each contain 0x13 (19) character pairs and are ended with checksums of
* 13 and 52, respectively. The fourth S1 record contains 07 character pairs and has a checksum of 92.
*
*   The S5 record is comprised as follows:
*
*     S5 S-record type S5, indicating it is a count record indicating the number of S1 records
*     03 Hexadecimal 03 (decimal 3), indicating that three character pairs follow.
*     00 04 Hexadecimal 0004 (decimal 4), indicating that there are four data records previous to this record.
*     F8 The checksum.
*
*   The S9 record is comprised as follows:
*
*     S9 S-record type S9, indicating it is a termination record.
*     03 Hexadecimal 03 (decimal 3), indicating that three character pairs follow.
*     00 00 The address field, hexadecimal 0 (decimal 0) indicating the starting execution address.
*     FC The checksum.
*
*********************************************************************************************************
*/

#ifndef SRECORD_H
#define SRECORD_H

/*
*********************************************************************************************************
*                                      INCLUDE
*********************************************************************************************************
*/

#include <stddef.h>

/*
*********************************************************************************************************
*                                      TYPE DEFINE
*********************************************************************************************************
*/

typedef unsigned char INT8U;
typedef unsigned long INT32U;

/*
*********************************************************************************************************
*                                      CONSTANT
*********************************************************************************************************
*/
// S-record only has defined type S0,S1,S2,S3,S5,S7,S8,S9
enum {
	SRECORD_TYPE_S0 = 0,
	SRECORD_TYPE_S1 = 1,
	SRECORD_TYPE_S2 = 2,
	SRECORD_TYPE_S3 = 3,
	// SRECORD_TYPE_S4,
	SRECORD_TYPE_S5 = 5,
	// SRECORD_TYPE_S6,
	SRECORD_TYPE_S7 = 7,
	SRECORD_TYPE_S8 = 8,
	SRECORD_TYPE_S9 = 9,
};

#define SRECORD_DATA_MAXCHARCNT    64
#define SRECORD_DATA_MAXLENGTH    (SRECORD_DATA_MAXCHARCNT / 2)

/*
*********************************************************************************************************
*                                      ERROR CODE
*********************************************************************************************************
*/

enum {
	SREC_ERR_NO,              // if success
	SREC_ERR_FORMAT,          // if error in format, e.g. first char is not 'S', char in DATA is not digit.
	SREC_ERR_TYPE,            // if type of record is invalid
	SREC_ERR_CHECKSUM,        // if the checksum is wrong.
	SREC_ERR_TOOSHORT,        // if the length of the record is too short
	SREC_ERR_TOOLONG,         // if the length of the record is too long
};
/*
*********************************************************************************************************
*                                      TYPE DEFINITION
*********************************************************************************************************
*/

typedef struct {
	INT8U RecType;
	INT8U DataLen;
	INT32U LoadAddr;
	INT8U Data[SRECORD_DATA_MAXLENGTH];       // hold datas that has been converted from hex char
} SRECORD_STRUCT;

/*
*********************************************************************************************************
*                                         PUBLIC FUNCTION
*********************************************************************************************************
*/

INT8U SRecord_StrToRec(INT8U *buf, SRECORD_STRUCT *result);
INT8U SRecord_RecToStr(SRECORD_STRUCT *srec, INT8U *result);

#endif
